]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
Fix hang when clicking on the user status menu in the overview
authorOwen W. Taylor <otaylor@fishsoup.net>
Fri, 28 Aug 2009 15:27:39 +0000 (11:27 -0400)
committerOwen W. Taylor <otaylor@fishsoup.net>
Fri, 28 Aug 2009 16:34:04 +0000 (12:34 -0400)
shell-global.[ch]: Add shell_global_display_is_grabbed() that
  uses the newly added meta_display_get_grab_op() to check
  for existing grabs.
shell-status-menu.[ch]: Add shell_status_menu_is_active() to
  check if the menu is popped up. Check for active grabs before
  popping the menu up. Use gtk_menu_popdown() rather than
  gtk_widget_hide(). Remove an excess gtk_widget_show() and
  some excess casts.
panel.js: Check whether the status menu is popped up after button
  release, and if it's not popped up, unhighlight the button.

Reported by Nuno Donato
http://bugzilla.gnome.org/show_bug.cgi?id=593362

js/ui/panel.js
src/shell-global.c
src/shell-global.h
src/shell-status-menu.c
src/shell-status-menu.h

index e01510999c22a8702361145d728e9afa338e49a2..5c9330ef1e6727e9e113040a3e3770634e449181 100644 (file)
@@ -381,6 +381,14 @@ Panel.prototype = {
             statusmenu.toggle(e);
             return false;
         });
+        // This depends on connection ordering: since we are after the Button's
+        // ::button-release-event handler, calling button.release() will properly
+        // unset the 'active' flag for this stays-pressed button
+        statusbutton.button.connect('button-release-event', function (b, e) {
+            if (!statusmenu.is_active())
+                statusbutton.release();
+            return false;
+        });
         this._rightBox.append(statusbutton.button, Big.BoxPackFlags.NONE);
         // We get a deactivated event when the popup disappears
         this._statusmenu.connect('deactivated', function (sm) {
index 6193e0eb6323237d3c61541d6d46b04b9856c926..f8eff40977df60c44b814aec080bb2fd3f6c652f 100644 (file)
@@ -512,6 +512,30 @@ shell_global_end_modal (ShellGlobal *global,
   mutter_plugin_end_modal (global->plugin, timestamp);
 }
 
+/**
+ * shell_global_display_is_grabbed
+ * @global: a #ShellGlobal
+ *
+ * Determines whether Mutter currently has a grab (keyboard or mouse or
+ * both) on the display. This could be the result of a current window
+ * management operation like a window move, or could be from
+ * shell_global_begin_modal().
+ *
+ * This function is useful to for ad-hoc checks to avoid over-grabbing
+ * the Mutter grab a grab from GTK+. Longer-term we might instead want a
+ * mechanism to make Mutter use GDK grabs instead of raw XGrabPointer().
+ *
+ * Return value: %TRUE if Mutter has a grab on the display
+ */
+gboolean
+shell_global_display_is_grabbed (ShellGlobal *global)
+{
+  MetaScreen *screen = mutter_plugin_get_screen (global->plugin);
+  MetaDisplay *display = meta_screen_get_display (screen);
+
+  return meta_display_get_grab_op (display) != META_GRAB_OP_NONE;
+}
+
 /* Code to close all file descriptors before we exec; copied from gspawn.c in GLib.
  *
  * Authors: Padraig O'Briain, Matthias Clasen, Lennart Poettering
index a3ad26397ca163933b8bed1323a0ad68c2c390b1..3cda07b56b26bc765bd312c54c3640d594e78a8c 100644 (file)
@@ -69,6 +69,8 @@ gboolean shell_global_begin_modal (ShellGlobal *global,
 void     shell_global_end_modal   (ShellGlobal *global,
                                   guint32      timestamp);
 
+gboolean shell_global_display_is_grabbed (ShellGlobal *global);
+
 void shell_global_reexec_self (ShellGlobal *global);
 
 void shell_global_format_time_relative_pretty (ShellGlobal *global, guint delta, char **text, guint *update_time);
index a5b1ccd7817d64c9264ca512daa2dd7da4e87965..4018faf3cd00a528e68469385a1f761e962c854f 100644 (file)
@@ -660,23 +660,53 @@ position_menu (GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer user
   *y = (gint)(0.5 + src_y + height);
 }
 
+/**
+ * shell_status_menu_toggle:
+ * @menu: a #ShellStatusMenu
+ *
+ * If the menu is not currently up, pops it up. Otherwise, hides it.
+ * Popping up may fail if another grab is already active; check with
+ * shell_status_menu_is_active().
+ */
 void
 shell_status_menu_toggle (ShellStatusMenu *status, ClutterEvent *event)
 {
   ShellStatusMenuPrivate *priv = status->priv;
 
-  if (GTK_WIDGET_VISIBLE (GTK_WIDGET (priv->menu)))
+  if (GTK_WIDGET_VISIBLE (priv->menu))
     {
-      gtk_widget_hide (GTK_WIDGET (priv->menu));
+      gtk_menu_popdown (GTK_MENU (priv->menu));
     }
   else
     {
-      gtk_widget_show (GTK_WIDGET (priv->menu));
+      /* We don't want to overgrab a Mutter grab with the grab that GTK+
+       * uses on menus.
+       */
+      ShellGlobal *global = shell_global_get ();
+      if (shell_global_display_is_grabbed (global))
+        return;
+
       gtk_menu_popup (GTK_MENU (priv->menu), NULL, NULL, position_menu,
-          status, 1, event->button.time);
+                      status, 1, event->button.time);
     }
 }
 
+/**
+ * shell_status_menu_is_active:
+ * @menu: a #ShellStatusMenu
+ *
+ * Gets whether the menu is currently popped up
+ *
+ * Return value: %TRUE if the menu is currently popped up
+ */
+gboolean
+shell_status_menu_is_active (ShellStatusMenu *status)
+{
+  ShellStatusMenuPrivate *priv = status->priv;
+
+  return GTK_WIDGET_VISIBLE (priv->menu);
+}
+
 /**
  * shell_status_menu_get_name:
  * @menu: a #ShellStatusMenu
index 983174187027e7d758ad35270e7ae000daa10e02..9a7c2969fc93dfb6a16c35bc7106eba8f4987093 100644 (file)
@@ -36,7 +36,7 @@ struct _ShellStatusMenuClass
 GType             shell_status_menu_get_type     (void);
 
 void              shell_status_menu_toggle       (ShellStatusMenu *menu, ClutterEvent *event);
-
+gboolean          shell_status_menu_is_active    (ShellStatusMenu *menu);
 ClutterText      *shell_status_menu_get_name     (ShellStatusMenu *menu);
 ClutterTexture   *shell_status_menu_get_icon     (ShellStatusMenu *menu);